home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / game / shoot / ADoomPPC_src.lha / ADoomPPC_src / w_wad.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-14  |  11.4 KB  |  629 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //    Handles WAD file header, directory, lump I/O.
  21. //
  22. //-----------------------------------------------------------------------------
  23.  
  24.  
  25. static const char
  26. rcsid[] = "$Id: w_wad.c,v 1.5 1997/02/03 16:47:57 b1 Exp $";
  27.  
  28.  
  29. #ifdef NORMALUNIX
  30. #if !defined(__SASC) && !defined(__GNUC__) && !defined(__VBCC__)
  31. #include <ctype.h>
  32. #include <sys/types.h>
  33. #include <string.h>
  34. #include <unistd.h>
  35. #include <malloc.h>
  36. #include <fcntl.h>
  37. #include <sys/stat.h>
  38. #include <alloca.h>
  39. #define O_BINARY 0
  40. #else
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <ctype.h>
  45. #ifdef __GNUC__
  46. #include <sys/stat.h>
  47. #elif !defined(__VBCC__)
  48. #include <stat.h>
  49. #endif
  50. #endif
  51. #endif
  52.  
  53.  
  54. #include "doomdef.h"
  55. #include "doomtype.h"
  56. #include "m_swap.h"
  57. #include "i_system.h"
  58. #include "z_zone.h"
  59.  
  60. #ifdef __GNUG__
  61. #pragma implementation "w_wad.h"
  62. #endif
  63. #include "w_wad.h"
  64.  
  65.  
  66.  
  67.  
  68. //
  69. // GLOBALS
  70. //
  71.  
  72. // Location of each lump on disk.
  73. lumpinfo_t*        lumpinfo;        
  74. int            numlumps;
  75.  
  76. void**            lumpcache;
  77.  
  78.  
  79. #if !defined(__SASC)
  80. #define strcmpi    strcasecmp
  81.  
  82. void strupr (char* s)
  83. {
  84.     while (*s) { *s = toupper(*s); s++; }
  85. }
  86. #endif
  87.  
  88. #ifdef __VBCC__
  89. int filelength (int handle)
  90. {
  91.         int size;
  92.         int oldpos;
  93.  
  94.         oldpos = ftell ((FILE *)handle);
  95.         fseek((FILE *)handle, 0, SEEK_END);
  96.         size = ftell ((FILE *)handle);
  97.         fseek ((FILE *)handle, oldpos, SEEK_SET);
  98.  
  99.         return size;
  100. }
  101. #else
  102. int filelength (int handle) 
  103.     struct stat    *fileinfo;
  104.     int size;
  105.     
  106.     if ((fileinfo = malloc (sizeof(struct stat))) == NULL ||
  107.         fstat (handle,fileinfo) == -1)
  108.     I_Error ("Error fstating");
  109.     size = fileinfo->st_size;
  110.     free (fileinfo);
  111.  
  112.     return size;
  113. }
  114. #endif
  115.  
  116. void
  117. ExtractFileBase
  118. ( char*        path,
  119.   char*        dest )
  120. {
  121.     char*    src;
  122.     int        length;
  123.  
  124.     src = path + strlen(path) - 1;
  125.     
  126.     // back up until a \ or the start
  127.     while (src != path
  128.        && *(src-1) != '\\'
  129.        && *(src-1) != '/')
  130.     {
  131.     src--;
  132.     }
  133.     
  134.     // copy up to eight characters
  135.     memset (dest,0,8);
  136.     length = 0;
  137.     
  138.     while (*src && *src != '.')
  139.     {
  140.     if (++length == 9)
  141.         I_Error ("Filename base of %s >8 chars",path);
  142.  
  143.     *dest++ = toupper((int)*src);
  144.         src++;
  145.     }
  146. }
  147.  
  148.  
  149.  
  150.  
  151.  
  152. //
  153. // LUMP BASED ROUTINES.
  154. //
  155.  
  156. //
  157. // W_AddFile
  158. // All files are optional, but at least one file must be
  159. //  found (PWAD, if all required lumps are present).
  160. // Files with a .wad extension are wadlink files
  161. //  with multiple lumps.
  162. // Other files are single lumps with the base filename
  163. //  for the lump name.
  164. //
  165. // If filename starts with a tilde, the file is handled
  166. //  specially to allow map reloads.
  167. // But: the reload feature is a fragile hack...
  168.  
  169. int            reloadlump;
  170. char*            reloadname;
  171.  
  172.  
  173. void W_AddFile (char *filename)
  174. {
  175.     wadinfo_t        header;
  176.     lumpinfo_t*        lump_p;
  177.     unsigned        i;
  178.     FILE        *handle;
  179.     int            length;
  180.     int            startlump;
  181.     filelump_t*        fileinfo = NULL;
  182.     filelump_t        singleinfo, *fi;
  183.     FILE        *storehandle;
  184.     int                 fileinfo_allocated = 0;
  185.     
  186.     // open the file and add to directory
  187.  
  188.     // handle reload indicator.
  189.     if (filename[0] == '~')
  190.     {
  191.     filename++;
  192.     reloadname = filename;
  193.     reloadlump = numlumps;
  194.     }
  195.         
  196.     if ( (handle = fopen (filename,"r")) == NULL)
  197.     {
  198.     printf (" couldn't open %s\n",filename);
  199.     return;
  200.     }
  201.  
  202.     printf (" adding %s\n",filename);
  203.     startlump = numlumps;
  204.     
  205.     if (strcmpi (filename+strlen(filename)-3 , "wad" ) )
  206.     {
  207.     // single lump file
  208.     fileinfo = &singleinfo;
  209.     singleinfo.filepos = 0;
  210. #ifdef __VBCC__
  211.     singleinfo.size = SWAPLONG(filelength((int)handle));
  212. #else
  213.     singleinfo.size = SWAPLONG(filelength(fileno(handle)));
  214. #endif
  215.     ExtractFileBase (filename, singleinfo.name);
  216.     numlumps++;
  217.     }
  218.     else 
  219.     {
  220.     // WAD file
  221.     fread (&header, 1, sizeof(header), handle);
  222.     if (strncmp(header.identification,"IWAD",4))
  223.     {
  224.         // Homebrew levels?
  225.         if (strncmp(header.identification,"PWAD",4))
  226.         {
  227.         I_Error ("Wad file %s doesn't have IWAD "
  228.              "or PWAD id\n", filename);
  229.         }
  230.         
  231.         // ???modifiedgame = true;        
  232.     }
  233.     header.numlumps = SWAPLONG(header.numlumps);
  234.     header.infotableofs = SWAPLONG(header.infotableofs);
  235.     length = header.numlumps*sizeof(filelump_t);
  236.     fileinfo = malloc (length);
  237.         fileinfo_allocated = 1;
  238.     fseek (handle, header.infotableofs, SEEK_SET);
  239.     fread (fileinfo, 1, length, handle);
  240.     numlumps += header.numlumps;
  241.     }
  242.  
  243.     
  244.     // Fill in lumpinfo
  245.     lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t));
  246.  
  247.     if (!lumpinfo)
  248.     I_Error ("Couldn't realloc lumpinfo");
  249.  
  250.     lump_p = &lumpinfo[startlump];
  251.     
  252.     storehandle = reloadname ? NULL : handle;
  253.  
  254.     fi = fileinfo;
  255.     for (i=startlump ; i<numlumps ; i++,lump_p++, fi++)
  256.     {
  257.     lump_p->handle = storehandle;
  258.     lump_p->position = SWAPLONG(fi->filepos);
  259.     lump_p->size = SWAPLONG(fi->size);
  260.     strncpy (lump_p->name, fi->name, 8);
  261.     }
  262.     
  263.     if (reloadname)
  264.     fclose (handle);
  265.     if (fileinfo_allocated)
  266.         free (fileinfo);
  267. }
  268.  
  269.  
  270.  
  271.  
  272. //
  273. // W_Reload
  274. // Flushes any of the reloadable lumps in memory
  275. //  and reloads the directory.
  276. //
  277. void W_Reload (void)
  278. {
  279.     wadinfo_t        header;
  280.     int            lumpcount;
  281.     lumpinfo_t*        lump_p;
  282.     unsigned        i;
  283.     FILE        *handle;
  284.     int            length;
  285.     filelump_t*        fileinfo = NULL;
  286.     filelump_t*         fi;
  287.  
  288.     if (!reloadname)
  289.     return;
  290.  
  291.     if ( (handle = fopen (reloadname,"r")) == NULL)
  292.     I_Error ("W_Reload: couldn't open %s",reloadname);
  293.  
  294.     fread (&header, 1, sizeof(header), handle);
  295.     lumpcount = SWAPLONG(header.numlumps);
  296.     header.infotableofs = SWAPLONG(header.infotableofs);
  297.     length = lumpcount*sizeof(filelump_t);
  298.     fileinfo = malloc (length);
  299.     fseek (handle, header.infotableofs, SEEK_SET);
  300.     fread (fileinfo, 1, length, handle);
  301.  
  302.     // Fill in lumpinfo
  303.     lump_p = &lumpinfo[reloadlump];
  304.     
  305.     fi = fileinfo;
  306.     for (i=reloadlump ;
  307.      i<reloadlump+lumpcount ;
  308.      i++,lump_p++, fi++)
  309.     {
  310.     if (lumpcache[i])
  311.         Z_Free (lumpcache[i]);
  312.  
  313.     lump_p->position = SWAPLONG(fi->filepos);
  314.     lump_p->size = SWAPLONG(fi->size);
  315.     }
  316.     
  317.     fclose (handle);
  318.     if (fileinfo != NULL)
  319.        free (fileinfo);
  320. }
  321.  
  322.  
  323.  
  324. //
  325. // W_InitMultipleFiles
  326. // Pass a null terminated list of files to use.
  327. // All files are optional, but at least one file
  328. //  must be found.
  329. // Files with a .wad extension are idlink files
  330. //  with multiple lumps.
  331. // Other files are single lumps with the base filename
  332. //  for the lump name.
  333. // Lump names can appear multiple times.
  334. // The name searcher looks backwards, so a later file
  335. //  does override all earlier ones.
  336. //
  337. void W_InitMultipleFiles (char** filenames)
  338. {    
  339.     int        size;
  340.     
  341.     // open all the files, load headers, and count lumps
  342.     numlumps = 0;
  343.  
  344.     // will be realloced as lumps are added
  345.     lumpinfo = malloc(1);    
  346.  
  347.     for ( ; *filenames ; filenames++)
  348.     W_AddFile (*filenames);
  349.  
  350.     if (!numlumps)
  351.     I_Error ("W_InitFiles: no files found");
  352.     
  353.     // set up caching
  354.     size = numlumps * sizeof(*lumpcache);
  355.     lumpcache = malloc (size);
  356.     
  357.     if (!lumpcache)
  358.     I_Error ("Couldn't allocate lumpcache");
  359.  
  360.     memset (lumpcache,0, size);
  361. }
  362.  
  363.  
  364.  
  365.  
  366. //
  367. // W_InitFile
  368. // Just initialize from a single file.
  369. //
  370. void W_InitFile (char* filename)
  371. {
  372.     char*    names[2];
  373.  
  374.     names[0] = filename;
  375.     names[1] = NULL;
  376.     W_InitMultipleFiles (names);
  377. }
  378.  
  379.  
  380.  
  381. //
  382. // W_NumLumps
  383. //
  384. int W_NumLumps (void)
  385. {
  386.     return numlumps;
  387. }
  388.  
  389.  
  390.  
  391. //
  392. // W_CheckNumForName
  393. // Returns -1 if name not found.
  394. //
  395.  
  396. int W_CheckNumForName (char* name)
  397. {
  398.     union {
  399.     char    s[9];
  400.     int    x[2];
  401.     
  402.     } name8;
  403.     
  404.     int        v1;
  405.     int        v2;
  406.     lumpinfo_t*    lump_p;
  407.  
  408.     // make the name into two integers for easy compares
  409.     strncpy (name8.s,name,8);
  410.  
  411.     // in case the name was a fill 8 chars
  412.     name8.s[8] = 0;
  413.  
  414.     // case insensitive
  415.     strupr (name8.s);        
  416.  
  417.     v1 = name8.x[0];
  418.     v2 = name8.x[1];
  419.  
  420.  
  421.     // scan backwards so patch lump files take precedence
  422.     lump_p = lumpinfo + numlumps;
  423.  
  424.     while (lump_p-- != lumpinfo)
  425.     {
  426.     if ( *(int *)lump_p->name == v1
  427.          && *(int *)&lump_p->name[4] == v2)
  428.     {
  429.         return lump_p - lumpinfo;
  430.     }
  431.     }
  432.  
  433.     // TFB. Not found.
  434.     return -1;
  435. }
  436.  
  437.  
  438.  
  439.  
  440. //
  441. // W_GetNumForName
  442. // Calls W_CheckNumForName, but bombs out if not found.
  443. //
  444. int W_GetNumForName (char* name)
  445. {
  446.     int    i;
  447.  
  448.     i = W_CheckNumForName (name);
  449.     
  450.     if (i == -1)
  451.       I_Error ("W_GetNumForName: %s not found!", name);
  452.       
  453.     return i;
  454. }
  455.  
  456.  
  457. //
  458. // W_LumpLength
  459. // Returns the buffer size needed to load the given lump.
  460. //
  461. int W_LumpLength (int lump)
  462. {
  463.     lumpinfo_t*    l;
  464.  
  465.     if (lump >= numlumps)
  466.     I_Error ("W_LumpLength: %i >= numlumps",lump);
  467.  
  468.     l = lumpinfo+lump;
  469.  
  470.     return l->size;    //lumpinfo[lump].size;
  471. }
  472.  
  473.  
  474.  
  475. //
  476. // W_ReadLump
  477. // Loads the lump into the given buffer,
  478. //  which must be >= W_LumpLength().
  479. //
  480. void
  481. W_ReadLump
  482. ( int        lump,
  483.   void*        dest )
  484. {
  485.     int        c;
  486.     lumpinfo_t*    l;
  487.     FILE    *handle;
  488.  
  489.     if (lump >= numlumps)
  490.     I_Error ("W_ReadLump: %i >= numlumps",lump);
  491.  
  492.     l = lumpinfo+lump;
  493.     // ??? I_BeginRead ();
  494.     
  495.     if (l->handle == NULL)
  496.     {
  497.     // reloadable file, so use open / read / close
  498.     if ( (handle = fopen (reloadname,"r")) == NULL)
  499.         I_Error ("W_ReadLump: couldn't open %s",reloadname);
  500.     }
  501.     else
  502.     handle = l->handle;
  503.     fseek (handle, l->position, SEEK_SET);
  504.       c = fread (dest, 1, l->size, handle);
  505.  
  506.     if (c < l->size)
  507.     I_Error ("W_ReadLump: only read %i of %i on lump %i",
  508.          c,l->size,lump);    
  509.  
  510.     if (l->handle == NULL)
  511.     fclose (handle);
  512.         
  513.     // ??? I_EndRead ();
  514. }
  515.  
  516.  
  517.  
  518. //
  519. // W_CacheLumpNum
  520. //
  521. void*
  522. W_CacheLumpNum
  523. ( int        lump,
  524.   int        tag )
  525. {
  526.     byte*    ptr;
  527.     int        llen;
  528.  
  529.     if ((unsigned)lump >= numlumps)
  530.     I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
  531.         
  532.     if (!lumpcache[lump])
  533.     {
  534.     // read the lump in
  535.     
  536. //    printf ("cache miss on lump %i\n",lump);
  537.         llen = W_LumpLength (lump);
  538.     ptr = Z_Malloc (llen, tag, &lumpcache[lump]);
  539.         if ((ptr == NULL) || (ptr != lumpcache[lump]))
  540.           I_Error ("cache allocation error on lump %i\n",lump);
  541.     W_ReadLump (lump, lumpcache[lump]);
  542.     }
  543.     else
  544.     {
  545. //    printf ("cache hit on lump %i\n",lump);
  546.     Z_ChangeTag (lumpcache[lump],tag);    // no error checking
  547.     }
  548.     return lumpcache[lump];
  549. }
  550.  
  551.  
  552.  
  553. //
  554. // W_CacheLumpName
  555. //
  556. void*
  557. W_CacheLumpName
  558. ( char*        name,
  559.   int        tag )
  560. {
  561.     return W_CacheLumpNum (W_GetNumForName(name), tag);
  562. }
  563.  
  564.  
  565. #if 0
  566. //
  567. // W_Profile
  568. //
  569. FAR int        info[2500][10];
  570. int        profilecount;
  571.  
  572. void W_Profile (void)
  573. {
  574.     int        i;
  575.     memblock_t*    block;
  576.     void*    ptr;
  577.     char    ch;
  578.     FILE*    f;
  579.     int        j;
  580.     char    name[9];
  581.     
  582.     
  583.     for (i=0 ; i<numlumps ; i++)
  584.     {    
  585.     ptr = lumpcache[i];
  586.     if (!ptr)
  587.     {
  588.         ch = ' ';
  589.         continue;
  590.     }
  591.     else
  592.     {
  593.         block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
  594.         if (block->tag < PU_PURGELEVEL)
  595.         ch = 'S';
  596.         else
  597.         ch = 'P';
  598.     }
  599.     info[i][profilecount] = ch;
  600.     }
  601.     profilecount++;
  602.     
  603.     f = fopen ("waddump.txt","w");
  604.     name[8] = 0;
  605.  
  606.     for (i=0 ; i<numlumps ; i++)
  607.     {
  608.     memcpy (name,lumpinfo[i].name,8);
  609.  
  610.     for (j=0 ; j<8 ; j++)
  611.         if (!name[j])
  612.         break;
  613.  
  614.     for ( ; j<8 ; j++)
  615.         name[j] = ' ';
  616.  
  617.     fprintf (f,"%s ",name);
  618.  
  619.     for (j=0 ; j<profilecount ; j++)
  620.         fprintf (f,"    %c",info[i][j]);
  621.  
  622.     fprintf (f,"\n");
  623.     }
  624.     fclose (f);
  625. }
  626. #endif
  627.  
  628.